﻿#region References
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using JigLibX.Collision;
using JigLibX.Physics;
using JigLibX.Geometry;
using JigLibX.Math;
using Microsoft.Xna.Framework.Graphics;
using Xen;
#endregion

namespace Ness.Engine.Entities
{
    class Player : Prop
    {
        public string playerID;
        public Character CharacterBody { get; set; }
        public Capsule capsule;

        public Player(Engine game, string model_path, Vector3 position, string id)
            : base(game, model_path, true, false)
        {
            playerID = id;

            body = new Character();
            collision = new CollisionSkin(body);

            SetSize(20.0f);

            Vector3 com = SetMass(10.0f);

            body.MoveTo(position + com, Matrix.Identity);
            collision.ApplyLocalTransform(new Transform(-com, Matrix.Identity));

            body.SetBodyInvInertia(0.0f, 0.0f, 0.0f);

            CharacterBody = body as Character;

            body.AllowFreezing = false;
            body.EnableBody();
        }

        public void SetSize(float size)
        {
            capsule = new Capsule(Vector3.Zero, Matrix.CreateRotationX(MathHelper.PiOver2), 1.0f, size);
            collision.AddPrimitive(capsule, (int)MaterialTable.MaterialID.NotBouncyNormal);
            body.CollisionSkin = this.collision;
        }
    }

    class Character : Body
    {
        public int healthPoints = 100;
        public bool noclip;

        public Character()
            : base()
        {
        }

        public Vector3 DesiredVelocity { get; set; }

        private bool doJump = false;

        public void DoJump()
        {
            doJump = true;
        }


        public override void AddExternalForces(float dt)
        {
            ClearForces();
            if (!noclip)
            {
                if (doJump)
                {
                    foreach (CollisionInfo info in CollisionSkin.Collisions)
                    {
                        Vector3 N = info.DirToBody0;
                        if (this == info.SkinInfo.Skin1.Owner)
                            Vector3.Negate(ref N, out N);

                        if (Vector3.Dot(N, Orientation.Up) > 0.7f)
                        {
                            Vector3 vel = Velocity; vel.Y = 13.0f;
                            Velocity = vel;
                            break;
                        }
                    }
                }

                Vector3 deltaVel = DesiredVelocity - Velocity;

                bool running = true;

                if (DesiredVelocity.LengthSquared() < JiggleMath.Epsilon) running = false;
                else deltaVel.Normalize();

                deltaVel.Y = 0.0f;

                // start fast, slow down slower
                if (running) deltaVel *= 10.0f;
                else deltaVel *= 2.0f;

                float forceFactor = 1000.0f;

                AddBodyForce(deltaVel * Mass * dt * forceFactor);

                doJump = false;
                AddGravityToExternalForce();
            }
        }
    }
}
